renderborder: Add API to query the outline clip
authorBenjamin Otte <otte@redhat.com>
Sun, 21 Feb 2016 00:01:41 +0000 (01:01 +0100)
committerBenjamin Otte <otte@redhat.com>
Sun, 21 Feb 2016 00:02:51 +0000 (01:02 +0100)
And use it in implementation of gadgets.

gtk/gtkcssgadget.c
gtk/gtkrenderborder.c
gtk/gtkrenderborderprivate.h

index eee448c2bd9f2addc7a234afaa368a01f3cce99f..7a254ebe698474d2a382b415cc2b8ac1939ef625 100644 (file)
@@ -601,6 +601,7 @@ gtk_css_gadget_allocate (GtkCssGadget        *gadget,
 {
   GtkCssGadgetPrivate *priv = gtk_css_gadget_get_instance_private (gadget);
   GtkAllocation content_allocation;
+  GtkAllocation tmp_clip;
   GtkAllocation content_clip = { 0, 0, 0, 0 };
   GtkBorder margin, border, padding, shadow, extents;
   GtkCssStyle *style;
@@ -669,6 +670,14 @@ gtk_css_gadget_allocate (GtkCssGadget        *gadget,
 
   if (content_clip.width > 0 && content_clip.height > 0)
     gdk_rectangle_union (&content_clip, out_clip, out_clip);
+
+  if (gtk_css_style_render_outline_get_clip (style,
+                                             allocation->x + margin.left,
+                                             allocation->y + margin.top,
+                                             allocation->width - margin.left - margin.right,
+                                             allocation->height - margin.top - margin.bottom,
+                                             &tmp_clip))
+    gdk_rectangle_union (&tmp_clip, out_clip, out_clip);
 }
 
 /**
index 47fdba43d4738133183f8882d9707c334d0b1fa4..f755f9f005f3d2d662f11c5b47be2897bc4d9be5 100644 (file)
@@ -691,6 +691,18 @@ render_border (cairo_t       *cr,
   cairo_restore (cr);
 }
 
+gboolean
+gtk_css_style_render_has_border (GtkCssStyle *style)
+{
+  if (_gtk_css_image_value_get_image (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE)))
+    return TRUE;
+
+  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_TOP_WIDTH), 100) > 0
+      || _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH), 100) > 0
+      || _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH), 100) > 0
+      || _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH), 100) > 0;
+}
+
 void
 gtk_css_style_render_border (GtkCssStyle      *style,
                              cairo_t          *cr,
@@ -745,6 +757,70 @@ gtk_css_style_render_border (GtkCssStyle      *style,
     }
 }
 
+gboolean
+gtk_css_style_render_border_get_clip (GtkCssStyle  *style,
+                                      gdouble       x,
+                                      gdouble       y,
+                                      gdouble       width,
+                                      gdouble       height,
+                                      GdkRectangle *out_clip)
+{
+  if (!gtk_css_style_render_has_border (style))
+    return FALSE;
+
+  out_clip->x = floor (x);
+  out_clip->y = floor (y);
+  out_clip->width = ceil (x + width) - out_clip->x;
+  out_clip->height = ceil (y + height) - out_clip->y;
+
+  return TRUE;
+}
+
+gboolean
+gtk_css_style_render_has_outline (GtkCssStyle *style)
+{
+  return _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100) > 0;
+}
+
+static void
+compute_outline_rect (GtkCssStyle       *style,
+                      gdouble            x,
+                      gdouble            y,
+                      gdouble            width,
+                      gdouble            height,
+                      cairo_rectangle_t *out_rect)
+{
+  double offset, owidth;
+
+  owidth = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
+  offset = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_OFFSET), 100);
+
+  if (width <= -2 * offset)
+    {
+      x += width / 2;
+      out_rect->x = x - owidth;
+      out_rect->width = 2 * owidth;
+    }
+  else
+    {
+      out_rect->x = x - offset - owidth;
+      out_rect->width = width + 2 * (offset + owidth);
+    }
+
+  if (height <= -2 * offset)
+    {
+      y += height / 2;
+      out_rect->y = y - owidth;
+      out_rect->height = 2 * owidth;
+    }
+  else
+    {
+      out_rect->y = y - offset - owidth;
+      out_rect->height = height + 2 * (offset + owidth);
+    }
+
+}
+                      
 void
 gtk_css_style_render_outline (GtkCssStyle *style,
                               cairo_t     *cr,
@@ -761,24 +837,42 @@ gtk_css_style_render_outline (GtkCssStyle *style,
   border_style[0] = _gtk_css_border_style_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_STYLE));
   if (border_style[0] != GTK_BORDER_STYLE_NONE)
     {
-      int offset;
+      cairo_rectangle_t rect;
+
+      compute_outline_rect (style, x, y, width, height, &rect);
 
       border_style[1] = border_style[2] = border_style[3] = border_style[0];
       border_width[0] = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_WIDTH), 100);
       border_width[3] = border_width[2] = border_width[1] = border_width[0];
       colors[0] = *_gtk_css_rgba_value_get_rgba (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_COLOR));
       colors[3] = colors[2] = colors[1] = colors[0];
-      offset = _gtk_css_number_value_get (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_OUTLINE_OFFSET), 100);
 
-      _gtk_rounded_box_init_rect (&border_box, x, y, width, height);
-      _gtk_rounded_box_shrink (&border_box,
-                               - border_width[GTK_CSS_TOP] - offset,
-                               - border_width[GTK_CSS_RIGHT] - offset,
-                               - border_width[GTK_CSS_LEFT] - offset,
-                               - border_width[GTK_CSS_BOTTOM] - offset);
+      _gtk_rounded_box_init_rect (&border_box, rect.x, rect.y, rect.width, rect.height);
       _gtk_rounded_box_apply_outline_radius_for_style (&border_box, style, GTK_JUNCTION_NONE);
 
       render_border (cr, &border_box, border_width, 0, colors, border_style);
     }
 }
 
+gboolean
+gtk_css_style_render_outline_get_clip (GtkCssStyle  *style,
+                                       gdouble       x,
+                                       gdouble       y,
+                                       gdouble       width,
+                                       gdouble       height,
+                                       GdkRectangle *out_clip)
+{
+  cairo_rectangle_t rect;
+
+  if (!gtk_css_style_render_has_outline (style))
+    return FALSE;
+
+  compute_outline_rect (style, x, y, width, height, &rect);
+
+  out_clip->x = floor (rect.x);
+  out_clip->y = floor (rect.y);
+  out_clip->width = ceil (rect.x + rect.width) - out_clip->x;
+  out_clip->height = ceil (rect.y + rect.height) - out_clip->y;
+
+  return TRUE;
+}
index 9c5a75411422b323e0dab5eb754eb4f26694c3e8..b72010e985832286fec2cc0c0732e236832d14a6 100644 (file)
 
 G_BEGIN_DECLS
 
-void    gtk_css_style_render_border     (GtkCssStyle            *style,
-                                         cairo_t                *cr,
-                                         gdouble                 x,
-                                         gdouble                 y,
-                                         gdouble                 width,
-                                         gdouble                 height,
-                                         guint                   hidden_side,
-                                         GtkJunctionSides        junction);
-void    gtk_css_style_render_outline    (GtkCssStyle            *style,
-                                         cairo_t                *cr,
-                                         gdouble                 x,
-                                         gdouble                 y,
-                                         gdouble                 width,
-                                         gdouble                 height);
+gboolean        gtk_css_style_render_has_border         (GtkCssStyle            *style);
+void            gtk_css_style_render_border             (GtkCssStyle            *style,
+                                                         cairo_t                *cr,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height,
+                                                         guint                   hidden_side,
+                                                         GtkJunctionSides        junction);
+gboolean        gtk_css_style_render_border_get_clip    (GtkCssStyle            *style,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height,
+                                                         GdkRectangle           *out_clip) G_GNUC_WARN_UNUSED_RESULT;
+
+gboolean        gtk_css_style_render_has_outline        (GtkCssStyle            *style);
+void            gtk_css_style_render_outline            (GtkCssStyle            *style,
+                                                         cairo_t                *cr,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height);
+gboolean        gtk_css_style_render_outline_get_clip   (GtkCssStyle            *style,
+                                                         gdouble                 x,
+                                                         gdouble                 y,
+                                                         gdouble                 width,
+                                                         gdouble                 height,
+                                                         GdkRectangle           *out_clip) G_GNUC_WARN_UNUSED_RESULT;
+
 
 G_END_DECLS